/*
*          iMaple by KururuLABO
*/

package iMaple.Packet;

import client.MapleCharacter;
import client.MapleClient;
import client.MapleTrait;
import client.inventory.Item;
import client.inventory.MapleInventory;
import client.inventory.MapleInventoryType;
import constants.GameConstants;
import static constants.GameConstants.getCurrentDate;
import handling.SendPacketOpcode;
import iMaple.iContants;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import tools.HexTool;
import tools.MaplePacketCreator;
import tools.Randomizer;
import tools.data.LittleEndianAccessor;
import tools.data.MaplePacketLittleEndianWriter;
import static tools.packet.PacketHelper.getTime;


public class CharlistRequest {

    public static final void CharlistRequest(LittleEndianAccessor slea, MapleClient c)
    {
        slea.readByte();
        byte server = slea.readByte();
        c.setWorld(server);
        c.setChannel(server + 1);
        System.out.println("SERVER : "+server);
        System.out.println("CH : "+server+1);
        //c.sendCharList(server);
        c.getSession().write(getCharList(c, server));
    }
    public static byte[] getCharList(MapleClient c, int serverId) {
        MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
        mplew.writeShort(SendPacketOpcode.CHARLIST.getValue());
        mplew.write(0);
        List<MapleCharacter> chars = c.loadCharacters(serverId);
        mplew.write((byte) chars.size());
        for (MapleCharacter chr : chars) {
            addCharEntry(mplew, chr, false);
        }
        mplew.write(c.getSecondPassword() != null && c.getSecondPassword().length() > 0 ? 1 : (c.getSecondPassword() != null && c.getSecondPassword().length() <= 0 && GameConstants.GMS ? 2 : 0)); // second pw request
        
        
        mplew.write(0);
        mplew.writeLong(c.getCharacterSlots());
        mplew.writeInt(-1); // FF FF FF FF
        mplew.writeLong(Randomizer.nextLong());
        mplew.write(0);
        mplew.writeLong(Randomizer.nextLong());
        return mplew.getPacket();
    }
    public static final byte[] addNewCharEntry(final MapleCharacter chr, final boolean worked) {
        final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();

        mplew.writeShort(SendPacketOpcode.ADD_NEW_CHAR_ENTRY.getValue());
        mplew.write(worked ? 0 : 1);
        addCharEntry(mplew, chr, false);

        return mplew.getPacket();
    }
    public static void addCharEntry(MaplePacketLittleEndianWriter mplew, MapleCharacter chr, boolean viewall) {
        addCharStats(mplew, chr);
        addCharLook(mplew, chr,false);
    }
    public static void addCharStats(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
        //mplew.write(HexTool.getByteArrayFromHexString("0C 00 05 00 04 00 04 00 32 00 00 00 32 00 00 00 32 00 00 00 32 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 27 00 00 02 00 00 00 58 32 FD 77 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 E0 FD 3B 37 4F 01 00 00 00 00 0A 00 00 00 00 05 06 00 00 00 00 00 3B 37 4F 01 00 40 E0 FD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 69 9E CE 01 80 78 76 D1 00 00 00 00 14 01 0A 00 4B 75 72 75 72 75 4C 41 42 4F 01 0A 00 4B 75 72 75 72 75 4C 41 42 4F 00 00 00 00 00 00 00 00 00 20 20 20 20 3C 00 40 E0 FD 3B 37 4F 01 05 00 01 86 DE 0F 00 00 00 80 05 BB 46 E6 17 02 FF FF FF FF FF FF FF 00 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 FF FF FF FF 00 00 00 00 00 00 04 00 00 00 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF 00 40 E0 FD 3B 37 4F 01 FF FF FF FF 06 00 01 A2 2C 10 00 00 00 80 05 BB 46 E6 17 02 FF FF FF FF FF FF FF 00 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 FF FF FF FF 00 00 00 00 00 00 04 00 00 00 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF 00 40 E0 FD 3B 37 4F 01 FF FF FF FF 07 00 01 81 5B 10 00 00 00 80 05 BB 46 E6 17 02 FF FF FF FF FF FF FF 00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 FF FF FF FF 00 00 00 00 00 00 04 00 00 00 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF 00 40 E0 FD 3B 37 4F 01 FF FF FF FF 0B 00 01 15 2C 14 00 00 00 80 05 BB 46 E6 17 02 FF FF FF FF FF FF FF 00 07 00 00 00 00 00 00 00 00 00 00 00 00 00 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 FF FF FF FF 00 00 00 00 00 00 04 00 00 00 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF 00 40 E0 FD 3B 37 4F 01 FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 02 00 0C 00 00 00 01 00 00 00 00 80 05 BB 46 E6 17 02 49 00 00 00 00 00 00 00 00 80 05 BB 46 E6 17 02 00 00 00 00 01 00 00 00 00 01 0D 00 38 7C 80 14 A0 12 CE 9C CE 01 50 58 80 14 A0 12 CE 9C CE 01 C4 5A 80 14 A0 12 CE 9C CE 01 C9 79 80 14 A0 12 CE 9C CE 01 D4 62 80 14 A0 12 CE 9C CE 01 E8 5A 80 14 A0 12 CE 9C CE 01 C3 5A 80 14 A0 12 CE 9C CE 01 69 20 80 14 A0 12 CE 9C CE 01 6A 20 80 14 A0 12 CE 9C CE 01 AD 2B 80 14 A0 12 CE 9C CE 01 AE 2B 80 14 A0 12 CE 9C CE 01 AF 2B 80 14 A0 12 CE 9C CE 01 B3 2B 80 14 A0 12 CE 9C CE 01 00 00 00 00 00 00 00 00 FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B FF C9 9A 3B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 E0 FD 3B 37 4F 01 00 00 00 00 00 08 00 43 72 65 61 74 69 6E 67 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 38 E0 FB 32 9F CE 01 00 00 00 00 01 00 00 00 00 00 00 28 D2 00 00 04 00 00 00 00 00 00 00 75 96 8F 00 00 00 00 00 76 96 8F 00 00 00 00 00 77 96 8F 00 00 00 00 00 78 96 8F 00 00 00 00 00 80 78 76 D1 69 9E CE 01 64 00 00 00 00 00 01"));
            
        mplew.writeInt(chr.getId());
        mplew.writeAsciiString(chr.getName(),13);
        mplew.write(chr.getGender());
        mplew.write(chr.getSkinColor());
        mplew.writeInt(chr.getFace());
        mplew.writeInt(chr.getHair());
        mplew.write(chr.getLevel());
        mplew.writeShort(chr.getJob());
        
        mplew.writeShort(chr.getStat().str);
        mplew.writeShort(chr.getStat().dex);
        mplew.writeShort(chr.getStat().int_);
        mplew.writeShort(chr.getStat().luk);
        mplew.writeInt(chr.getStat().hp);
        mplew.writeInt(chr.getStat().maxhp);
        mplew.writeInt(chr.getStat().mp);
        mplew.writeInt(chr.getStat().maxmp);
        mplew.writeShort(chr.getRemainingAp());
        mplew.writeShort(chr.getRemainingSp());
        mplew.writeInt(chr.getExp());
        mplew.writeInt(chr.getFame());
        mplew.writeInt(chr.getGachExp());
        if(iContants.isXenon(chr.getJob()) || iContants.isResistance(chr.getJob()) || iContants.isEvan(chr.getJob()) || iContants.isMercedes(chr.getJob()) || iContants.isPhantom(chr.getJob()) || iContants.isMihile(chr.getJob()) || iContants.isLuminous(chr.getJob()) || iContants.isKaiser(chr.getJob()) || iContants.isAngelicBurter(chr.getJob()) || iContants.isDemon(chr.getJob()))
        {
            mplew.writeZeroBytes(7);//UNK
        }
        else if(iContants.isCannonshooter(chr.getJob()) || iContants.isAdventure(chr.getJob()) || iContants.isCygnus(chr.getJob()) || iContants.isAran(chr.getJob()) || iContants.isDualblade(chr.getJob()))
        {
            mplew.writeZeroBytes(8);//UNK
        }
        mplew.writeInt(chr.getMapId());
        mplew.write(chr.getInitialSpawnpoint());//1
        mplew.writeShort(chr.getSubcategory());
        if(iContants.isXenon(chr.getJob()) || iContants.isDemon(chr.getJob()))
        {
            mplew.writeInt(chr.getDemonMarking());
        }
        mplew.write(chr.getFatigue());
        mplew.writeInt(getCurrentDate());
        mplew.writeInt(chr.getTrait(MapleTrait.MapleTraitType.charisma).getTotalExp());
        mplew.writeInt(chr.getTrait(MapleTrait.MapleTraitType.insight).getTotalExp());
        mplew.writeInt(chr.getTrait(MapleTrait.MapleTraitType.will).getTotalExp());
        mplew.writeInt(chr.getTrait(MapleTrait.MapleTraitType.craft).getTotalExp());
        mplew.writeInt(chr.getTrait(MapleTrait.MapleTraitType.sense).getTotalExp());
        mplew.writeInt(chr.getTrait(MapleTrait.MapleTraitType.charm).getTotalExp());
        mplew.writeShort(chr.getTrait(MapleTrait.MapleTraitType.charisma).getTraitsGainToday());
        mplew.writeShort(chr.getTrait(MapleTrait.MapleTraitType.insight).getTraitsGainToday());
        mplew.writeShort(chr.getTrait(MapleTrait.MapleTraitType.will).getTraitsGainToday());
        mplew.writeShort(chr.getTrait(MapleTrait.MapleTraitType.craft).getTraitsGainToday());
        mplew.writeShort(chr.getTrait(MapleTrait.MapleTraitType.sense).getTraitsGainToday());
        mplew.writeShort(chr.getTrait(MapleTrait.MapleTraitType.charm).getTraitsGainToday());
        mplew.write(0);//IDK 00
        mplew.writeLong(getTime(-2L));
        mplew.writeInt(chr.getStat().pvpExp);
        mplew.write(chr.getStat().pvpRank);
        mplew.writeInt(chr.getBattlePoints());
        mplew.write(5);
        mplew.write(6);
        mplew.writeInt(0);
        mplew.write(0);
        mplew.writeLong(Randomizer.nextLong());
        mplew.writeInt(0);
        mplew.write(0);
        mplew.writeZeroBytes(81);
        mplew.writeLong(Randomizer.nextLong());
        mplew.writeInt(0);
    }
    public static void addCharLook(MaplePacketLittleEndianWriter mplew, MapleCharacter chr,boolean mega) {
        mplew.write(chr.getGender());
        mplew.write(chr.getSkinColor());
        mplew.writeInt(chr.getFace());
        mplew.writeInt(chr.getJob());
        mplew.write(mega ? 1 : 0);//MEGA?
        mplew.writeInt(chr.getHair());//76 8E 00 00 

        addCharEquips(mplew, chr);
    }
    
    public static void addCharEquips(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
        final Map<Byte, Integer> myEquip = new LinkedHashMap<>();
        final Map<Byte, Integer> maskedEquip = new LinkedHashMap<>();
        MapleInventory equip = chr.getInventory(MapleInventoryType.EQUIPPED);

        for (final Item item : equip.newList()) {
            if (item.getPosition() < -127) { //not visible
                continue;
            }
            byte pos = (byte) (item.getPosition() * -1);

            if (pos < 100 && myEquip.get(pos) == null) {
                myEquip.put(pos, item.getItemId());
            } else if (pos > 100 && pos != 111) {
                pos = (byte) (pos - 100);
                if (myEquip.get(pos) != null) {
                    maskedEquip.put(pos, myEquip.get(pos));
                }
                myEquip.put(pos, item.getItemId());
            } else if (myEquip.get(pos) != null) {
                maskedEquip.put(pos, item.getItemId());
            }
        }
        for (final Map.Entry<Byte, Integer> entry : myEquip.entrySet()) {
            mplew.write(entry.getKey());
            mplew.writeInt(entry.getValue());
        }
        
        mplew.write(0xFF);
        for (final Map.Entry<Byte, Integer> entry : maskedEquip.entrySet()) {
            mplew.write(entry.getKey());
            mplew.writeInt(entry.getValue());
        }
        mplew.write(0xFF);
        mplew.writeInt(0);//UNK 00 00 00 00
        Item Weapon = equip.getItem((byte)-11);
        mplew.writeInt(Weapon !=null ? Weapon.getItemId() : 0);
        mplew.write(iContants.isMercedes(chr.getJob()) ? 1 : 0);
       
        
        if(iContants.isCannonshooter(chr.getJob()) || iContants.isAdventure(chr.getJob()) || iContants.isCygnus(chr.getJob()) || iContants.isAran(chr.getJob()) || iContants.isDualblade(chr.getJob()) || iContants.isResistance(chr.getJob()) ||  iContants.isEvan(chr.getJob()) || iContants.isMercedes(chr.getJob()) || iContants.isPhantom(chr.getJob()) || iContants.isMihile(chr.getJob()) || iContants.isLuminous(chr.getJob()) || iContants.isKaiser(chr.getJob()) || iContants.isAngelicBurter(chr.getJob()))
        {
            mplew.writeZeroBytes(18);
        }
        else if(iContants.isXenon(chr.getJob()) || iContants.isDemon(chr.getJob()))
        {
            mplew.writeZeroBytes(16);
            mplew.writeInt(chr.getDemonMarking());
            mplew.writeZeroBytes(2);
        }
        
        
    }
}
